package com.erp.erp_ui.Process;

import com.erp.erp_entitys.Activiti.LeaveTaskEntity;
import com.erp.erp_entitys.Process.ProcessEntity;
import com.erp.erp_entitys.Role.RoleEntity;
import com.erp.erp_entitys.Role.RoleExample;
import com.erp.erp_entitys.RoleGroupMember.RoleGroupMemberEntity;
import com.erp.erp_entitys.User.UserEntity;
import com.erp.erp_entitys.User.UserEntityExample;
import com.erp.erp_servers.Role.IRoleService;
import com.erp.erp_servers.RoleGroupMember.IRoleGroupMemberService;
import com.erp.erp_servers.User.IUserService;
import com.erp.erp_ui.Activiti.Entity.ProcessDBSL;
import com.erp.erp_ui.Activiti.FlowUtils;
import com.erp.erp_ui.Activiti.ProcessService;
import com.erp.erp_ui.Activiti.service.IProcessSerivce;
import com.erp.erp_ui.base.Base;
import com.erp.utils.R;
import com.erp.utils.ResultStatusEnum;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.*;

@Controller
@RequestMapping(value = "process")
public class ProcessControl extends Base {
    @Autowired
    IUserService userService;
    @Autowired
    IRoleGroupMemberService roleGroupMemberService;
    @Autowired
    IRoleService roleService;
    @Autowired
    IProcessSerivce processSerivce;
    /**
     * 查询用户待办任务列表。
     *
     * @return 任务列表
     */
    @RequestMapping(value = "queryToDoTasks")
    @ResponseBody
    public R<List<LeaveTaskEntity>> queryToDoTasks(String processKey){
        try {
            UserEntity user = (UserEntity)this.getBean("user");
            String assignee=user.getCode();
            List<LeaveTaskEntity> leaveTaskEntities = ProcessService.queryToDoTasks2(assignee, processKey);
            String ids="";
            for(int i=0;i<leaveTaskEntities.size();i++){
                LeaveTaskEntity lte=leaveTaskEntities.get(i);
                if(i==leaveTaskEntities.size()-1){
                    ids=ids+lte.getProcessInstanceId();
                }else{
                    ids=ids+lte.getProcessInstanceId()+",";
                }
            }
            List<ProcessEntity> processEntities = processSerivce.queryListById(ids);
            for(ProcessEntity pe:processEntities){
                String processId = pe.getProcessid();
                for(LeaveTaskEntity lte:leaveTaskEntities){
                    if(processId.equals(lte.getProcessInstanceId())){
                        lte.setCode(pe.getCode());
                        lte.setTotalCost(pe.getTotalCost());
                        break;
                    }
                }
            }
            return R.build(leaveTaskEntities);
        }catch (Exception e){
            e.printStackTrace();
            return R.buildError(ResultStatusEnum.ERROR);
        }
    }
    /**
     * 查询已处理任务列表。
     *
     * @return 已处理任务列表
     */
    @RequestMapping(value = "queryDoneTasks")
    @ResponseBody
    public   R<List<LeaveTaskEntity>> queryDoneTasks() {
        try {
            UserEntity user = (UserEntity)this.getBean("user");
            String assignee=user.getCode();
            return R.build(ProcessService.queryDoneTasks(assignee));
        }catch (Exception e){
            e.printStackTrace();
            return R.buildError(ResultStatusEnum.ERROR);
        }
    }
    /**
     * 查询用户待办任务列表数量。
     * @return 任务列表
     */
    @RequestMapping(value = "queryToDoTasksCount")
    @ResponseBody
    public R<List<ProcessDBSL>> queryToDoTasksCount(){
        try {
            UserEntity user = (UserEntity)this.getBean("user");
            String assignee=user.getCode();
            List<LeaveTaskEntity> leaveTaskEntities = ProcessService.queryToDoTasks(assignee);
            Map<String,Integer> map=new HashMap<>();
            Map<String,String> mp=new HashMap<>();
            for(int i=0;i<leaveTaskEntities.size();i++){
                LeaveTaskEntity leaveTaskEntity = leaveTaskEntities.get(i);
                String processDefinitionId = leaveTaskEntity.getProcessDefinitionId();
                ProcessDefinition processDefinition = ProcessService.queryProcessDefinition(processDefinitionId);
                /*if(!processDefinition.getKey().equals(processKey)){
                    break;
                }*/
                String sptype=processDefinitionId.split(":")[0];
                if(map.get(sptype) !=null){
                    map.put(sptype,map.get(sptype)+1);
                }else{
                    map.put(sptype,1);
                }

                mp.put(sptype,processDefinition.getName());
                //mp.put("processKey",processDefinition.getKey());
            }
            List<ProcessDBSL> list=new ArrayList<>();
            for(Map.Entry<String,Integer> entry:map.entrySet()){
                String mapKey = entry.getKey();
                int mapValue = entry.getValue();
                String typeName=mp.get(mapKey);

                ProcessDBSL p=new ProcessDBSL();
                p.setSptype(typeName);
                p.setSpcount(mapValue+"");
                p.setProcessKey(mapKey);
                list.add(p);
            }
            return R.build(list);
        }catch (Exception e){
            e.printStackTrace();
            return R.buildError(ResultStatusEnum.ERROR);
        }
    }
    /**
     * 查询已处理任务列表数量。
     *
     * @return 已处理任务列表
     */
    @RequestMapping(value = "queryDoneTasksCount")
    @ResponseBody
    public   R<Integer> queryDoneTasksCount( ) {
        try {
            UserEntity user = (UserEntity)this.getBean("user");
            String assignee=user.getCode();
            return R.build(ProcessService.queryDoneTasks(assignee).size());
        }catch (Exception e){
            e.printStackTrace();
            return R.buildError(ResultStatusEnum.ERROR);
        }
    }
    /**
     * 提交流程/流程转向
     * @param taskId
     *            当前任务ID
     * @param variables
     *            流程变量
     * @param activityId
     *            流程转向执行任务节点ID<br>
     *            此参数为空，默认为提交操作
     * @throws Exception
     */
    @RequestMapping(value = "commitProcess")
    @ResponseBody
    public R<Boolean> commitProcess(String taskId, Map<String, Object> variables, String activityId,String comment){
        try{
            ActivityImpl activitiImpl = ProcessService.findActivitiImpl(taskId, activityId);
            comment=activitiImpl.getProperty("name")+"通过["+comment+"]";
            //判断当前节点是否是最后一个节点

            Map<String,String> map=ProcessService.isFinalTask(taskId,activityId);

            UserEntity user = (UserEntity)this.getBean("user");
            //TaskDefinition nextTask = ProcessService.getNextTask(taskId);
            variables.putAll( getNextSpr( taskId));//获取下一节点审批人
           // getNextSpr( taskId);
            ProcessService.commitProcess(taskId,variables,activityId,comment,user.getName());
            if(map.get("tf").equals("true")){

                boolean b = processSerivce.updateStatus(map.get("processKey"), map.get("bid"),"2");
            }
            return R.build(true);
        }catch (Exception e){
            e.printStackTrace();
            return R.buildError(ResultStatusEnum.ERROR);
        }

    }
    /**
     * 驳回流程
     *
     * @param taskId
     *            当前任务ID
     *            驳回节点ID
     * @param variables
     *            流程存储参数
     * @throws Exception
     */
    @RequestMapping(value = "backProcess")
    @ResponseBody
    public  R<Boolean> backProcess(String taskId ,Map<String, Object> variables,String comment){
        try{
            comment=ProcessService.findActivitiImpl(taskId, null).getProperty("name")+"驳回["+comment+"]";
            //根据当前任务ID，查询可以驳回的任务节点集
            List<ActivityImpl> backAvtivity = ProcessService.findBackAvtivity(taskId);
            if(backAvtivity.size()==0){
                return R.build(false);
            }else{
                //根据任务id获取流程实例
                ProcessInstance processInstance=ProcessService.findProcessInstanceByTaskId(taskId);
                //根据流入任务集合，查询最近一次的流入任务节点
                ActivityImpl activity = ProcessService.filterNewestActivity(processInstance, backAvtivity);
                //驳回,activityId为前一节点
                String activityid=activity.getId();
                ProcessService.backProcess(taskId,activityid,variables,comment, getUser().getName());
                return R.build(true);
            }

        }catch (Exception e){
            e.printStackTrace();
            return R.buildError(ResultStatusEnum.ERROR);
        }
    }
    /**
     * 查询 审批日志
     * @param taskId
     * @return
     */
    @RequestMapping(value = "getProcessComments")
    @ResponseBody
    public R<List<Comment>> getProcessComments(String taskId){
        try {
            List<Comment> processComments = ProcessService.getProcessComments(taskId);
            return R.build(processComments);
        }catch (Exception e){
            e.printStackTrace();
            return R.buildError(ResultStatusEnum.ERROR);
        }
    }

    /**
     * 根据taskId获取自定义表单及业务主键
     * @param taskId
     * @return
     */
    @RequestMapping(value = "getFormInfo")
    @ResponseBody
    public R<Map<String,String>> getFormInfo(String taskId){
        try {
            String formKey = ProcessService.getFormInfo(taskId);//表单
            String businessKey = ProcessService.getBusinessKey(taskId);
            List<String> list=new ArrayList<String>();
            Map<String,String> map=new HashMap<String,String>();
            map.put("formkey",formKey);
            map.put("businesskey",businessKey);
            return R.build(map);
        }catch (Exception e){
            e.printStackTrace();
            return R.buildError(ResultStatusEnum.ERROR);
        }
    }

    /**
     * 获取流程图
     * @param response
     * @param processId  流程id
     */
    @RequestMapping(value = "traceprocess")
    @ResponseBody
    public void traceprocess(HttpServletResponse response, String processId){
        try {
            FlowUtils flowUtils=new FlowUtils();
            InputStream in = flowUtils.getResourceDiagramInputStream(processId);
            ServletOutputStream output = response.getOutputStream();
            IOUtils.copy(in, output);
        }catch (Exception e){
            e.printStackTrace();
           // return R.buildError(ResultStatusEnum.ERROR);
        }
    }

    /**
     * 获取下一节点审批人
     * @param taskId
     * @return
     * @throws Exception
     */
    private Map<String, Object> getNextSpr(String taskId)throws Exception{
        Map<String, Object> map=new HashMap<>();
        TaskDefinition nextTask = ProcessService.getNextTask(taskId);
        if(nextTask==null) return map;
        Expression assigneeExpression = nextTask.getAssigneeExpression();
        Set<Expression> candidateUserIdExpressions = nextTask.getCandidateUserIdExpressions();
        Set<Expression> candidateGroupIdExpressions = nextTask.getCandidateGroupIdExpressions();
        String a="";
        String u="";
        String g="";
        String ru="";
        String rg="";
        if(candidateUserIdExpressions.size() >0){
           /* String role=cl(candidateUserIdExpressions.iterator().next());
            variables.put(role,getUserByRole(role));*/
            ru = candidateUserIdExpressions.iterator().next().getExpressionText().replace("${","").replace("}","");
            u=getUserByRole(ru);
        }
        if(candidateGroupIdExpressions.size()>0){
            rg= candidateGroupIdExpressions.iterator().next().getExpressionText().replace("${","").replace("}","");
           g=getUserGroupByRole(rg);
        }
        if(assigneeExpression !=null){
            a=assigneeExpression.getExpressionText();
        }

        /*if(a !=null)   return a;*/
        if(!ru.equals("")){
            map.put(ru,u);
        }
        if(!rg.equals("")) {
             map.put(rg,g);
        }
        if(!a.equals("")  && a.indexOf("$") !=-1){
            map.put(a.replace("${","").replace("}",""),a);
        }

        return map;
    }
    /**
     *
     * @param processDefId 流程定义id
     * @param bid 业务主键
     * @param variables 流程参数(,一定要有下个节点的审批人，即在流程图中配置的审批人变量)
     * @param  totalCost 单据总额
     * @param code  单据编码
     * @return
     */
    @RequestMapping(value = "startProcess")
    @ResponseBody
    public R<String> startProcess(String processDefId, String bid, Map<String, Object> variables , String code,String totalCost){
        try{
            UserEntity user = (UserEntity)this.getBean("user");
            if(variables ==null) variables=new HashMap<String, Object>();
            UserTask fristTaskSpr = ProcessService.getFristTaskSpr(processDefId);
            String assignee = fristTaskSpr.getAssignee();
            List<String> candidateGroups = fristTaskSpr.getCandidateGroups();
            List<String> candidateUsers = fristTaskSpr.getCandidateUsers();
            if(candidateUsers.size() >0){
                String role=cl(candidateUsers.get(0));
                variables.put(role,getUserByRole(role));
            }
            if(candidateGroups.size()>0){
                String role=cl(candidateGroups.get(0));
                variables.put(role,getUserGroupByRole(role));
            }

            String processid = ProcessService.startProcess(processDefId,bid+"",variables,user.getCode() );//"customer"
            //根据流程定义key、与bid来更新业务表流程状态
            ProcessEntity process=new ProcessEntity();
            process.setCode(code);
            process.setTotalCost(totalCost);
            process.setProcessid(processid);
            processSerivce.insert(process);
            boolean b = processSerivce.updateStatus(processDefId, bid,"1");
            return R.build(processid);
        }catch (Exception e){
            e.printStackTrace();
            return R.buildError(ResultStatusEnum.ERROR);
        }
    }
    private String cl(String role){
        role=role.replace("${","").replace("}","");
        return role;
    }
    private String getUserByRole(String role){
        UserEntityExample example=new UserEntityExample();
        UserEntityExample.Criteria criteria = example.createCriteria();
        criteria.andRolesLike("%"+role+"%");
        List<UserEntity> userEntities = userService.selectByExample(example);
        //  List<String> list=new ArrayList<>();
        String user="";
        for(int i=0;i<userEntities.size();i++){
            if(i==userEntities.size()-1){
                user+=userEntities.get(i).getCode();
            }else{
                user+=userEntities.get(i).getCode()+",";
            }

        }
        return user;
    }
    private String getUserGroupByRole(String grouprole){
        try{
            String users="";
            List<RoleEntity> roleEntities=new ArrayList<RoleEntity>();

            RoleGroupMemberEntity record=new RoleGroupMemberEntity();
            record.setGroupCode(grouprole);
            List<RoleGroupMemberEntity> roleGroupMemberEntities = roleGroupMemberService.selectByExample(record);
            if(roleGroupMemberEntities.size()==0) return users;
            List<String> listRoleCode=new ArrayList<String>();
            for(int i=0;i<roleGroupMemberEntities.size();i++){
                listRoleCode.add(roleGroupMemberEntities.get(i).getRoleCode());
            }
            RoleExample example=new RoleExample();
            RoleExample.Criteria criteria = example.createCriteria();
            criteria.andCodeIn(listRoleCode);
            roleEntities = roleService.selectByExample(example);
            //获取人
            UserEntityExample example1=new UserEntityExample();
            UserEntityExample.Criteria criteria1 = example1.createCriteria();
            for(int i=0;i<roleEntities.size();i++){
                criteria1.andRolesLike("%"+roleEntities.get(i).getCode()+"%");
            }
            List<UserEntity> userEntities = userService.selectByExample(example1);
            for(int i=0;i<userEntities.size();i++){
                if(i==userEntities.size()-1){
                    users+=userEntities.get(i).getCode();
                }else{
                    users+=userEntities.get(i).getCode()+",";
                }
            }
            return users;
        }catch (Exception e){
            e.printStackTrace();
            return "";
        }

    }
}
